// cli_core.c
#include "../inc/cli_core.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../inc/serial_service.h"

static const Command *g_commands = NULL;

void registerCommands(const Command *cmdList) { g_commands = cmdList; }

int parseCommandLine(char *cmd, char **argv, int maxArgc)
{
    int argc = 0;

    while (*cmd && argc < maxArgc)
    {
        while (isspace((unsigned char)*cmd)) *cmd++ = '\0';
        if (*cmd == '\0')
            break;

        if (*cmd == '"')
        {
            argv[argc++] = ++cmd;
            while (*cmd && *cmd != '"') cmd++;
            if (*cmd == '"')
                *cmd++ = '\0';
        }
        else
        {
            argv[argc++] = cmd;
            while (*cmd && !isspace((unsigned char)*cmd)) cmd++;
            if (*cmd)
                *cmd++ = '\0';
        }
    }

    return argc;
}

void parseSerialCommand(uint8_t *buffer, size_t length)
{
    if (length < 2 || buffer[length - 2] != '\r' || buffer[length - 1] != '\n')
    {
        Serial_Printf("Invalid command: missing \\r\\n\n");
        return;
    }

    buffer[length - 2] = '\0';
    char *cmd          = (char *)buffer;

    char *argv[16];
    int   argc = parseCommandLine(cmd, argv, 16);

    if (argc == 0)
        return;

    for (int i = 0; g_commands[i].name != NULL; i++)
    {
        if (strcmp(g_commands[i].name, argv[0]) == 0)
        {
            g_commands[i].handler(argc - 1, argv + 1);
            return;
        }
    }

    Serial_Printf("Unknown command: %s\n", argv[0]);
}

int cli_help(int argc, char **argv)
{
    if (argc == 0)
    {
        Serial_Printf("Available commands:\n");
        for (int i = 0; g_commands[i].name != NULL; i++)
        {
            Serial_Printf("  %s - %s\n", g_commands[i].name, g_commands[i].help);
        }
        return 0;
    }

    for (int i = 0; g_commands[i].name != NULL; i++)
    {
        if (strcmp(g_commands[i].name, argv[0]) == 0)
        {
            Serial_Printf("%s - %s\n", g_commands[i].name, g_commands[i].help);
            g_commands[i].handler(1, (char *[]){"-h"});
            return 0;
        }
    }

    Serial_Printf("Unknown command: %s\n", argv[0]);
    return -1;
}